package com.bcx.wind.workflow.imp.cmd.managercmd;

import com.bcx.wind.workflow.WindEngine;
import com.bcx.wind.workflow.access.QueryFilter;
import com.bcx.wind.workflow.core.constant.TaskLevel;
import com.bcx.wind.workflow.core.constant.TaskStatus;
import com.bcx.wind.workflow.core.constant.TaskType;
import com.bcx.wind.workflow.entity.*;
import com.bcx.wind.workflow.errorcontext.WindError;
import com.bcx.wind.workflow.interceptor.Command;
import com.bcx.wind.workflow.interceptor.CommandContext;
import com.bcx.wind.workflow.pojo.StrandUser;
import com.bcx.wind.workflow.pojo.Wind;
import com.bcx.wind.workflow.pojo.WindUser;
import com.bcx.wind.workflow.support.Assert;
import com.bcx.wind.workflow.support.JsonHelper;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.bcx.wind.workflow.core.constant.Constant.ARRAY_NULL;
import static com.bcx.wind.workflow.core.constant.Constant.JSON_NULL;
import static com.bcx.wind.workflow.core.constant.OrderVariableConstant.*;
import static com.bcx.wind.workflow.message.ErrorCode.*;

/**
 * 加签命令
 *
 * @author zhanglei
 */
public class AddApproveUsersCommand implements Command<List<WindTask>> {

    /**
     * 任务ID
     */
    private String taskId;

    /**
     * 添加的审批人
     */
    private List<WindUser> windUsers;


    /**
     * 当前用户
     */
    private WindUser user;


    /**
     * 历史履历模板
     */
    private WindActHistory history;


    /**
     * 当前任务所属流程实例
     */
    private WindOrder windOrder;


    /**
     * 历史履历中的审批人数据
     */
    private String historyApproveUser = ARRAY_NULL;


    /**
     * 执行数据
     */
    private CommandContext commandContext;

    private List<WindTask> result = new LinkedList<>();

    public AddApproveUsersCommand(String taskId,List<WindUser> windUsers,WindUser user){
        this.taskId = taskId;
        this.windUsers = windUsers;
        this.user = user;
    }

    @Override
    public List<WindTask> executor(CommandContext context) {
        try{
            this.commandContext = context;
            return execute();
        }catch (Exception e){
            context.log(e);
            return null;
        }
    }

    /**
     * 校验任务ID
     * @return  返回任务
     */
    private WindTask checkTaskId(){
        Assert.notEmptyError(ADD_APPROVE_USER_TASK_NOT_FOUND,this.taskId);
        QueryFilter filter = new QueryFilter()
                .setTaskId(taskId)
                .setStatus(TaskStatus.run.name());
        List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);
        Assert.notEmptyError(ADD_APPROVE_USER_TASK_NOT_FOUND,windTasks);
        WindTask task = windTasks.get(0);
        //流程实例
        this.windOrder = this.commandContext.access().getOrderInstanceById(task.getOrderId());
        return task;
    }


    private  void checkWindUsers(WindTask windTask){
        Assert.notEmptyError(ADD_APPROVE_USER_NOT_FOUND,this.windUsers);
        //查询当前流程当前节点所有任务
        QueryFilter filter = new QueryFilter()
                .setOrderId(windTask.getOrderId())
                .setTaskName(windTask.getTaskName())
                .setStatus(TaskStatus.run.name());
        List<WindTask> windTasks = this.commandContext.access().selectTaskInstanceList(filter);

        //查询这些任务的审批人集合
        if(!ObjectHelper.isEmpty(windTasks)) {

            List<String> taskIds = windTasks.stream().map(WindTask::getId).collect(Collectors.toList());
            QueryFilter actorFilter = new QueryFilter()
                    .setTaskIds(taskIds.toArray(new String[]{}));
            List<WindTaskActor> actors = this.commandContext.access().selectTaskActorList(actorFilter);
            //审批人ID集合
            List<String> actorIds = actors.stream().map(WindTaskActor::getActorId).collect(Collectors.toList());
            for (WindUser wu : this.windUsers) {
                Assert.notEmptyError(ADD_APPROVE_USER_NOT_FOUND, wu.getUserId());
                //审批人已经存在
                Assert.isTrueError(ADD_APPROVE_USER_IS_EXIST,actorIds.contains(wu.getUserId()));
            }
        }
    }


    private List<WindTask> execute() {
        //校验任务Id
        WindTask windTask = checkTaskId();
        //校验审批人
        checkWindUsers(windTask);
        //执行添加审批人
        addOperate(windTask);
        return result;
    }



    private void addOperate(WindTask windTask) {
        String taskType = windTask.getTaskType();
        //普通任务
        if(TaskType.ordinary.name().equals(taskType)){
            //普通任务只需要在任务上添加一个审批人即可，该审批人拥有该任务的审批权限，但是并不是必须要审批
            addOrdinaryTask(windTask);
        }
        //会签任务
        else if(TaskType.jointly.name().equals(taskType)){
            addJointlyTask(windTask);
        }
        //串签任务
        else if(TaskType.strand.name().equals(taskType)){
            addStrandTask(windTask);
        }else{
            WindError.error(TASK_NOT_SUPPORT_OPERATE,null);
        }

    }

    /**
     * 串签任务添加审批人
     *
     * 串签任务无需新建任务，审批人数据，也无需更新历史
     * @param windTask  当前任务
     */
    @SuppressWarnings("unchecked")
    private void  addStrandTask(WindTask windTask){

        if(this.windOrder != null){

            Map<String,Object> variable = this.windOrder.variable();
            Object strandApproveUserObj = variable.get(STRAND_APPROVE_USER);

            if(!ObjectHelper.isEmpty(strandApproveUserObj)){
                Map<String,Object> strandApproveUserMap = JsonHelper.objectToMap(strandApproveUserObj);

                Object  taskStrandUsers = strandApproveUserMap.get(windTask.getTaskName());
                if(!ObjectHelper.isEmpty(taskStrandUsers)){

                    List<StrandUser> strandUsers = JsonHelper.coverObject(taskStrandUsers,List.class,StrandUser.class);
                    //优先级最末的用户
                    StrandUser su = strandUsers.stream().max(Comparator.comparingInt(StrandUser::getSort))
                            .orElse(null);
                    if(su != null) {
                        int sort = su.getSort();
                        for (WindUser windUser : this.windUsers) {
                            sort ++;
                            StrandUser strandUser = new StrandUser()
                                    .setSort(sort)
                                    .setUser(windUser);
                            strandUsers.add(strandUser);
                        }

                        //更新操作
                        strandApproveUserMap.put(windTask.getTaskName(),strandUsers);
                        variable.put(STRAND_APPROVE_USER,strandApproveUserMap);
                        this.windOrder.setVariable(JsonHelper.toJson(variable));
                        this.commandContext.access().updateOrderInstance(this.windOrder);
                    }
                }

            }
        }

    }

    /**
     * 会签任务添加审批人
     * 会签任务需要创建和审批人数量相等的任务数量，添加这些新建任务的历史履历，然后更新流程实例中任务审批变量数据
     *
     *
     * @param windTask  会签任务
     */
    private void  addJointlyTask(WindTask windTask){
        int count = this.windUsers.size();
        //构建历史任务模板
        buildOldHistory();
        //构建历史履历待审批人数据
        buildApproveUsers();
        for(WindUser windUser : windUsers){
            //创建任务 以及审批人
            WindTask task = buildWindTask(windTask,windUser);
            //添加返回值
            this.result.add(windTask);
            //更新历史履历
            changeActHistory(task);
        }
        //更新流程实例审批人变量数据
        changeOrderVariableForJointly(windTask,count);
    }


    /**
     * 会签类型加签更新流程实例变量数据
     *
     */
    private void changeOrderVariableForJointly(WindTask windTask,int count){
        if(this.windOrder != null){

            Map<String,Object> variable = windOrder.variable();
            Object jointlyMinCount = variable.get(JOINTLY_MIN_COUNT);
            if(!ObjectHelper.isEmpty(jointlyMinCount)){
                Map<String,Object> map = JsonHelper.objectToMap(jointlyMinCount);

                if(!ObjectHelper.isEmpty(map)){
                    Object approveUserCount = map.get(windTask.getTaskName());

                    if (!ObjectHelper.isEmpty(approveUserCount)) {
                        Map<String,Object> approveUserCountMap = JsonHelper.objectToMap(approveUserCount);

                        if(!ObjectHelper.isEmpty(approveUserCountMap)){
                            Object successCount = approveUserCountMap.get(JOINTLY_SUCCESS_COUNT);
                            Object nowCount = approveUserCountMap.get(JOINTLY_NOW_COUNT);
                            if(!ObjectHelper.hasEmpty(successCount,nowCount)){
                                int success = Integer.parseInt(successCount.toString());
                                int now = Integer.parseInt(nowCount.toString());
                                //校验是否可以关闭
                                Assert.isTrueError(TASK_IS_ONLY,success - now <=1);
                                approveUserCountMap.put(JOINTLY_SUCCESS_COUNT,Integer.toString(success + count));
                                map.put(windTask.getTaskName(),approveUserCountMap);
                                variable.put(JOINTLY_MIN_COUNT,map);
                                this.windOrder.setVariable(JsonHelper.toJson(variable));
                                this.commandContext.access().updateOrderInstance(this.windOrder);
                            }
                        }
                    }

                }
            }

        }
    }


    /**
     * 更新历史履历t
     * 根据就的历史履历  结合着新建的任务，添加新的历史履历
     *
     * @param windTask    新的任务
     */
    private  void  changeActHistory(WindTask windTask){
        if(!ObjectHelper.isEmpty(this.history)){

            WindActHistory act = new WindActHistory()
                    .setId(ObjectHelper.primaryKey())
                    .setApproveUserVariable(this.historyApproveUser)
                    .setCreateTime(TimeHelper.nowDate())
                    .setOrderId(windTask.getOrderId())
                    .setProcessDisplayName(this.history.getProcessDisplayName())
                    .setProcessId(this.history.getProcessId())
                    .setProcessName(this.history.getProcessName())
                    .setSystem(this.history.getSystem())
                    .setTaskCreateUser(windTask.getCreateUser())
                    .setTaskId(windTask.getId())
                    .setTaskDisplayName(windTask.getDisplayName())
                    .setTaskName(windTask.getTaskName())
                    .setTaskType(windTask.getTaskType())
                    .setTaskLevel(TaskLevel.main.name());

            this.commandContext.access().insertActiveHistory(act);
        }

    }


    /**
     * 构建历史履历模板
     */
    private void buildOldHistory(){
        //查询出历史履历
        QueryFilter filter = new QueryFilter()
                .setTaskId(this.taskId);
        List<WindActHistory>  histories = this.commandContext.access().selectActiveHistoryList(filter);
        if(!ObjectHelper.isEmpty(histories)){
            this.history = histories.get(0);
        }
    }


    /**
     * 构建历史履历审批人数据
     */
    @SuppressWarnings("unchecked")
    private void  buildApproveUsers(){
        if(this.history != null){

            String approveUser  = this.history.getApproveUserVariable();
            if(approveUser != null){
                List<WindUser> users = JsonHelper.parseJson(approveUser,List.class,WindUser.class);
                users.addAll(this.windUsers);
                this.historyApproveUser = JsonHelper.toJson(users);
            }
        }
    }



    /**
     * 构建任务以及审批人
     *
     * @param windTask   任务模板，指定任务
     * @param user       添加审批人
     * @return           新建的任务
     */
    private WindTask buildWindTask(WindTask windTask, WindUser user){
        WindTask task =  new WindTask()
                .setId(ObjectHelper.primaryKey())
                .setStatus(windTask.getStatus())
                .setCreateTime(TimeHelper.nowDate())
                .setApproveCount(0)
                .setVariable(JSON_NULL)
                .setCreateUser(user().getUserId())
                .setDisplayName(windTask.getDisplayName())
                .setExpireTime(windTask.getExpireTime())
                .setOrderId(windTask.getOrderId())
                .setParentId(windTask.getParentId())
                .setPosition(windTask.getPosition())
                .setProcessId(windTask.getProcessId())
                .setTaskName(windTask.getTaskName())
                .setTaskType(windTask.getTaskType())
                .setVersion(1)
                .setTaskLevel(TaskLevel.main.name());

        WindTaskActor actor = new WindTaskActor()
                .setTaskId(task.getId())
                .setActorId(user.getUserId());
        this.commandContext.access().insertTaskInstance(task);
        this.commandContext.access().insertTaskActor(actor);

        return task;
    }



    /**
     * 普通任务 添加审批人
     *
     * @param windTask  普通任务
     */
    private void  addOrdinaryTask(WindTask windTask){
        for(WindUser u : windUsers){
            WindTaskActor actor = new WindTaskActor()
                    .setTaskId(windTask.getId())
                    .setActorId(u.getUserId());
            this.commandContext.access().insertTaskActor(actor);
        }
        this.result.add(windTask);
    }




    private WindUser user(){
        return this.user == null ? new WindUser()
                .setUserId("admin")
                .setUserName("管理员") : this.user;
    }

}
